package models

import (
	"bytes"
	"comment/util"
	"crypto/md5"
	"encoding/hex"
	"fmt"
	"strconv"
	"time"

	"github.com/astaxie/beego/orm"
)

type User struct {
	Id        int       `orm:"column(id);auto"`
	Account   string    `orm:"column(account);size(20)"`
	Password  string    `orm:"column(password);size(32)"`
	Status    int8      `orm:"column(status)"`
	Name      string    `orm:"column(name);size(10)"`
	Roles     int       `orm:"column(roles)"`
	JobNumber int       `orm:"column(job_number)"`
	Duty      string    `orm:"column(duty);size(20)"`
	Token     string    `orm:"column(token);size(32)"`
	Time      time.Time `orm:"column(time);type(datetime)"`
}

func (t *User) TableName() string {
	return "user"
}

func init() {
	orm.RegisterModel(new(User))
}

func PageUser(pageNo int, size int, query map[string]string) util.Page {
	o := orm.NewOrm()
	var user User
	var list []User
	qs := o.QueryTable(user)

	for k, v := range query {
		qs = qs.Filter(k, v)
	}

	count, _ := qs.Limit(-1).Count()
	qs.RelatedSel().Limit(size).Offset((pageNo-1)*size).All(&list, "Id", "Account", "Status", "Name", "Roles", "JobNumber", "Duty", "Time")
	c, _ := strconv.Atoi(strconv.FormatInt(count, 10))
	for j := 0; j < len(list); j++ {
		o.Raw("select name from role where id = ?", list[j].Roles).QueryRow(&list[j].Password)
	}
	return util.PageUtil(c, pageNo, size, list)
}

func FindUserByAccount(Account string) int {
	o := orm.NewOrm()
	var count int = 0
	o.Raw("select count(1) count from user where account = ?", Account).QueryRow(&count)
	return count
}

func FindUserByJobNumber(JobNumber int, Id int) int {
	o := orm.NewOrm()
	var count int = 0
	if Id == 0 {
		o.Raw("select count(1) count from user where job_number = ?", JobNumber).QueryRow(&count)
	} else {
		o.Raw("select count(1) count from user where job_number = ? and id != ? ", JobNumber, Id).QueryRow(&count)
	}
	return count
}

func SaveUser(user *User) (int64, error) {
	o := orm.NewOrm()
	h := md5.New()
	Password := user.Password
	h.Write([]byte(Password))
	user.Password = hex.EncodeToString(h.Sum(nil))

	t := bytes.Buffer{}
	t.WriteString(user.Account)
	t.WriteString(Password)
	token := t.String()

	token_h := md5.New()
	token_h.Write([]byte(token))
	user.Token = hex.EncodeToString(token_h.Sum(nil))

	//user.Token = token
	user.Time = time.Now()
	id, err := o.Insert(user)
	return id, err
}

func FindUserById(id int) User {
	o := orm.NewOrm()
	var user User
	o.QueryTable(user).Filter("Id", id).One(&user, "Id", "Account", "Status", "Name", "Roles", "JobNumber", "Duty")
	return user
}

func FindLikeUserByName(name string) interface{} {
	o := orm.NewOrm()
	var user User
	var users []User
	o.QueryTable(user).Filter("Name__contains", name).One(&users, "Id")
	array2 := make([]int, len(users))
	for index := range users {
		array2[index] = users[index].Id
	}
	return array2
}

func UpdateUser(user *User) {
	o := orm.NewOrm()
	user.Time = time.Now()
	o.Update(user, "Name", "Status", "Roles", "JobNumber", "Duty", "Time")
}

func UpdatePassword(user *User) {
	o := orm.NewOrm()
	h := md5.New()
	Password := user.Password
	h.Write([]byte(Password))
	user.Password = hex.EncodeToString(h.Sum(nil))
	user.Time = time.Now()
	o.Update(user, "Password", "Time")
}

func DeleteUser(id int, safeAccount string) (err error) {
	o := orm.NewOrm()
	v := User{Id: id}
	// ascertain id exists in the database
	if err = o.Read(&v); err == nil {
		if v.Account != safeAccount {
			var num int64
			if num, err = o.Delete(&User{Id: id}); err == nil {
				fmt.Println("Number of records deleted in database:", num)
			}
		} else {
			fmt.Println("系统安全账号不允许删除")
		}

	}
	return
}

func FindUserByToken(token string) (bool, User) {
	o := orm.NewOrm()
	var user User
	err := o.QueryTable(user).Filter("Token", token).One(&user)
	return err != orm.ErrNoRows, user
}

func GetRoleByRoleID(roleID int) Role {
	o := orm.NewOrm()
	var (
		role Role
	)
	o.QueryTable(&role).Filter("id", roleID).One(&role)
	return role
}
